﻿using System;
using Microsoft.Xna.Framework;
using RainEngine.SceneManagement;

namespace RainEngine.SceneNodes.UI
{
    /// <summary>
    /// 滚动条基类，水平滚动条和竖直滚动条从这个类继承
    /// </summary>
    public abstract class UIScrollBarBase:UISceneNode
    {
        #region 成员变量和构造函数

        /// <summary>
        /// 默认轨道图像矩形
        /// </summary>
        protected static readonly Rectangle DefaultSliderRailRect = new Rectangle(33, 32, 14, 16); 
       
        /// <summary>
        /// 默认滑块普通状态图像矩形
        /// </summary>
        protected static readonly Rectangle DefaultSliderButtonRectOrigin = new Rectangle(0, 32, 16, 16);

        /// <summary>
        /// 默认滑块高亮状态图像矩形
        /// </summary>
        protected static readonly Rectangle DefaultSliderButtonRectHighlight = new Rectangle(16, 32, 16, 16);

        /// <summary>
        /// 默认滑块点击状态图像矩形
        /// </summary>
        protected static readonly Rectangle DefaultSliderButtonRectClicked = new Rectangle(16, 32, 16, 16);

        /// <summary>
        /// 默认摩擦条图像矩形
        /// </summary>
        protected static readonly Rectangle DefaultSliderButtonGlyphRect = new Rectangle(48, 0, 16, 16);

        /// <summary>
        /// 滚动条按钮宽(高)，即滚动条高度，默认为16
        /// </summary>
        protected float buttonWidth;

        /// <summary>
        /// 向左(上)按钮
        /// </summary>
        protected UIButton btnLeftUp;
        
        /// <summary>
        /// 向左(上)按钮的位置
        /// </summary>
        protected Vector2 btnLeftUpPositon;

        /// <summary>
        /// 向右(下)按钮
        /// </summary>
        protected UIButton btnRightDown;

        /// <summary>
        /// 向右(下)按钮的位置
        /// </summary>
        protected Vector2 btnRightDownPosition;

        /// <summary>
        /// 按钮普通状态图像矩形
        /// </summary>
        protected Rectangle buttonRectOrigin;        

        /// <summary>
        /// 按钮高亮状态图像矩形
        /// </summary>
        protected Rectangle buttonRectHighlight;        

        /// <summary>
        /// 按钮点击状态图像矩形
        /// </summary>
        protected Rectangle buttonRectClicked;

        /// <summary>
        /// 滑动条的长（高），由滚动条宽（高）度减去2倍按钮宽（高）度得出，默认为200。
        /// </summary>
        protected float sliderRailSizeX;
        
        /// <summary>
        /// 滑动条轨道图像矩形
        /// </summary>
        protected Rectangle sliderRailRect;
        
        /// <summary>
        /// 滑块位置
        /// </summary>
        protected Vector2 sliderButtonPosition;

        /// <summary>
        /// 滑块长（高）度，由变量sliderRailSizeX，maxStep和largeChange计算得出，默认为160。
        /// </summary>
        protected float  sliderButtonSizeX;        

        /// <summary>
        /// 滑块普通状态图像矩形
        /// </summary>
        protected Rectangle sliderButtonRectOrigin;        

        /// <summary>
        /// 滑块高亮状态图像矩形
        /// </summary>
        protected Rectangle sliderButtonRectHighlight;
        
        /// <summary>
        /// 滑块点击状态图像矩形
        /// </summary>
        protected Rectangle sliderButtonRectClicked;        

        /// <summary>
        /// 滑动条轨道位置
        /// </summary>
        protected Vector2 sliderRailPosition;
        
        /// <summary>
        /// 摩擦条图像矩形
        /// </summary>
        protected Rectangle sliderButtonGlyphRect;

        /// <summary>
        /// 可以前进的最大步数，默认为1，即滑块移动1步就可以从最左边移动到最右边。
        /// </summary>
        protected int maxStep=1;

        /// <summary>
        /// 当用户单击滚动箭头时，滑块变动的幅度，默认为1，即一次移动一格。
        /// </summary>
        protected int smallChange = 1;

        /// <summary>
        /// 当用户单击滚动条时滑块移动的幅度，即一页显示的段数，默认为4。
        /// </summary>
        protected int largeChange = 4;        

        /// <summary>
        /// 滑动条的值，默认为0
        /// </summary>
        protected int value = 0;        

        /// <summary>
        /// 是否处在滑动状态
        /// </summary>
        protected bool isScrolling = false;

        /// <summary>
        /// 创建一个滚动条抽象基类，内部方法，只能在引擎内部调用。水平滚动条和竖直滚动条是从这个基类继承的。
        /// </summary>
        /// <param name="engine">引擎</param>
        /// <param name="setScene">所属场景</param>
        /// <param name="setSizee">控件大小</param>
        /// <param name="setPosition">2D屏幕位置</param>
        /// <param name="setTextureName">纹理文件名称</param>           
        /// <param name="setSliderButtonRectOrigin">滑动条按钮普通状态矩形</param>
        /// <param name="setSliderButtonRectHighlight">滑动条按钮高亮状态矩形</param>
        /// <param name="setSliderButtonRectClicked">滑动条按钮点击状态矩形</param>        
        /// <param name="setSliderRailRect">滑动条轨道图像矩形</param>
        /// <param name="setButtonRectOrigin">按钮普通状态图像矩形</param>        
        /// <param name="setButtonRectHighlight">按钮高亮状态图像矩形</param>
        /// <param name="setButtonRectClicked">按钮点击状态图像矩形</param>        
        /// <param name="setSliderButtonGlypgRect">摩擦条图像矩形</param>
        internal UIScrollBarBase(RainGE engine, Scene setScene, Vector2 setSize,Vector2 setPosition, string setTextureName,Rectangle setButtonRectOrigin, Rectangle setButtonRectHighlight, Rectangle setButtonRectClicked, Rectangle setSliderRailRect, Rectangle setSliderButtonRectOrigin, Rectangle setSliderButtonRectHighlight, Rectangle setSliderButtonRectClicked, Rectangle setSliderButtonGlypgRect,bool useResource)
            : base(engine ,setScene ,setPosition ,setTextureName,useResource )
        {
            this.size = setSize;
            
            //按钮图像矩形
            this.buttonRectOrigin = setButtonRectOrigin;
            this.buttonRectHighlight = setButtonRectHighlight;
            this.buttonRectClicked = setButtonRectClicked;            
            //轨道图像矩形
            this.sliderRailRect =setSliderRailRect;
            //滑块图像矩形
            this.sliderButtonRectOrigin =setSliderButtonRectOrigin ;
            this.sliderButtonRectHighlight =setSliderButtonRectHighlight ;
            this.sliderButtonRectClicked =setSliderButtonRectClicked;            
            //摩擦条图像矩形
            this.sliderButtonGlyphRect = setSliderButtonGlypgRect;
        }

        #endregion

        #region 属性

        /// <summary>
        /// 获取或设置按钮普通状态图像矩形
        /// </summary>
        public Rectangle ButtonRectOrigin
        {
            get { return buttonRectOrigin; }
            set { buttonRectOrigin = value; }
        }

        /// <summary>
        /// 获取或设置按钮高亮状态图像矩形
        /// </summary>
        public Rectangle ButtonRectHighlight
        {
            get { return buttonRectHighlight; }
            set { buttonRectHighlight = value; }
        }

        /// <summary>
        /// 获取或设置按钮点击状态图像矩形
        /// </summary>
        public Rectangle ButtonRectClicked
        {
            get { return buttonRectClicked; }
            set { buttonRectClicked = value; }
        }

        /// <summary>
        /// 获取滑动条的长（高）
        /// </summary>
        public float SliderRailSizeX
        {
            get { return sliderRailSizeX; }            
        }

        /// <summary>
        /// 获取滑块长度（高）
        /// </summary>
        public float SliderButtonSizeX
        {
            get { return sliderButtonSizeX; }

        }

        /// <summary>
        /// 获取或设置滑块普通状态图像矩形
        /// </summary>
        public Rectangle SliderButtonRectOrigin
        {
            get { return sliderButtonRectOrigin; }
            set { sliderButtonRectOrigin = value; }
        }

        /// <summary>
        /// 获取或设置滑块高亮状态图像矩形
        /// </summary>
        public Rectangle SliderButtonRectHighlight
        {
            get { return sliderButtonRectHighlight; }
            set { sliderButtonRectHighlight = value; }
        }

        /// <summary>
        /// 获取或设置滑块点击状态图像矩形
        /// </summary>
        protected Rectangle SliderButtonRectClicked
        {
            get { return sliderButtonRectClicked; }
            set { sliderButtonRectClicked = value; }
        }

        /// <summary>
        /// 获取或设置摩擦条图像矩形
        /// </summary>
        public Rectangle SliderButtonGlyphRect
        {
            get { return sliderButtonGlyphRect; }
            set { sliderButtonGlyphRect = value; }
        }

        /// <summary>
        /// 获取或设置滚动条的值
        /// </summary>
        public int Value
        {
            get { return this.value; }
            set
            {
                this.value = value;
                if (this.value < 0)
                    this.value = 0;
                else if (this.value > maxStep)
                    this.value = maxStep;
                OnValueChanged();
            }
        }

        /// <summary>
        /// 获取或设置当用户单击滚动条时滑块移动的幅度，即一页显示的段数，默认为4。
        /// </summary>
        public int LargeChange
        {
            get { return largeChange; }
            set
            {
                largeChange = value;
                Redraw();
            }
        }

        /// <summary>
        /// 获取或设置可以前进的最大步数，默认为1，即滑块移动1步就可以从最左边移动到最右边，当MaxStep为零时无需绘制滚动条。
        /// </summary>
        public int MaxStep
        {
            get { return maxStep; }
            set
            {
                maxStep = value;
                
                
                //如果maxStep小于0则将它重置为0，且将isVisible设为false，不显示箭头按钮。
                if (maxStep <= 0)
                {
                    maxStep = 0;
                    visible = btnLeftUp.Visible = btnRightDown.Visible = false;
                }
                //maxStep大于0且滚动条不可见，则将isVisible属性设为true，并显示箭头按钮
                else if (maxStep > 0 && visible == false)
                    visible = btnLeftUp.Visible = btnRightDown.Visible = true;

                if (this.value > maxStep)
                    this.value = maxStep;
                Redraw();
            }
        }

        /// <summary>
        /// 获取或设置当用户单击滚动箭头时，滑块变动的幅度，默认为1，即一次移动一格。
        /// </summary>
        public int SmallChange
        {
            get { return smallChange; }
            set
            {
                smallChange = value;
                if (smallChange > maxStep)
                    smallChange =maxStep ;
                
                Redraw();
            }
        }       

        #endregion      

        #region 事件相关处理程序

        /// <summary>
        /// 滑动条的值变化时引发的事件
        /// </summary>
        public event EventHandler ValueChanged;

        /// <summary>
        /// ValueChanged事件的处理程序，需要重新调整滑动条按钮的位置。
        /// OnValueChanged方法允许继承的类处理这个事件。
        /// 注意：当在继承类中覆写OnValueChanged时，一定要调用基类的OnValueChanged方法才可以注册委托
        /// </summary>        
        protected virtual void OnValueChanged()
        {
            ResetSliderButtonPosition();
            if (ValueChanged != null)
                ValueChanged(this.value, null);            
        }

        /// <summary>
        /// 点击下（右）按钮时的事件处理程序
        /// </summary>
        protected void btnDownRight_MouseClick(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            if (Value < maxStep)
            {
                Value += smallChange;                
            }
        }

        /// <summary>
        /// 点击上（左）按钮时的事件处理程序
        /// </summary>
        protected void btnUpLeft_MouseClick(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            if (value > 0)
            {
                Value -= smallChange;                
            }
        }

        /// <summary>
        /// 滚动条IsVisible属性改变时的处理程序
        /// </summary>
        protected override void OnVisibleChanged(EventArgs e)
        {
            base.OnVisibleChanged(e);
            if (maxStep <= 0)
                visible = false;
            btnLeftUp.Visible = visible ;
            btnRightDown.Visible = visible ;
        }

        /// <summary>
        /// 滚动条位置发生变化时需要重新绘制滚动条
        /// </summary>
        protected override void OnLocationChanged()
        {
            base.OnLocationChanged();
            Redraw();
        }

        /// <summary>
        /// 滚动条大小发生变化时需要重新绘制滚动条
        /// </summary>
        protected override void OnSizeChanged()
        {
            Redraw();
            base.OnSizeChanged();
        }

        /// <summary>
        /// 重新绘制滚动条
        /// </summary>
        protected virtual void Redraw()
        { }

        /// <summary>
        ///  重置滑块位置
        /// </summary>
        protected virtual void ResetSliderButtonPosition()
        { }

        #endregion
    }
}